#ifndef STATE_H
#define STATE_H

#include <stdint.h>
#include <iostream>
#include <vector>

#include "global.h"
#include "Instance.h"

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>

using namespace std;

//#define DEBUG

class State {
  private:
    uint16_t pNumber;		        // pocet uzlu
    vector<uint16_t> pColors;		// pole barev pro uzly
    uint16_t pMaxColor;	        // maximum barev
    uint16_t pLastColor;        // poslední nová barva
    uint16_t pNextNode;		      // dalsi uzel ktery zatim nema barvu

    /* BOOST SERIALIZATION */
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive& aAr, const unsigned int version) {
      aAr & pNumber;
      aAr & pMaxColor;
      aAr & pLastColor;
      aAr & pNextNode;
      aAr & pColors;
    }

  public: //lifetime
    // aInstance - pointer na graf, aFirst - pokud true, kazdy uzel ma svou vlastni barvu
    State(uint16_t aMaxColor = 0)
    {
      init(aMaxColor);
      clear();
    }

    // copy constructor
    State(const State& aState)
    {
      init(aState.pMaxColor);
      copy(aState);
    }

    State& operator= (const State& aState) {
      if (this != &aState) {
        init(aState.pMaxColor);
        copy(aState);
      }
      return *this;
    }

  public: //own methods
    const uint16_t& operator[] (uint16_t aIndex) const
    {
      /* range checking, disabled for greater speed */
      //if (aIndex >= pNumber)
      //throw "State subscript out of bounds";
      return pColors[aIndex];
    }

    uint16_t getMaxColor() const {
      return pMaxColor;
    }

    uint16_t& lastColor() {
      return pLastColor;
    }

    uint16_t getLastColor() const {
      return pLastColor;
    }

    uint16_t& nextNode() {
      return pColors[pNextNode++];
    }
  
    uint16_t getNode() const {
      return pNextNode;
    }

    bool isFinal() const {
      return pNextNode == pNumber;
    }

    //je to platný stav, kontroluje jenom posledni pridany node!
    bool willBeValid(uint16_t aColor) const {
      for (uint16_t i=0;i<pNumber;++i) {
        if (i == pNextNode) continue;
        if (gInstance(pNextNode,i) && pColors[i] == aColor) return false;
      }
      return true;
    }

    friend ostream &operator<<(ostream &aOut, const State& aState);

  private: //lifetime
    void init(uint16_t aMaxColor) {
      pNumber = gInstance.getNumber();
      pMaxColor = aMaxColor;
      pLastColor = 0;
      pColors.resize(pNumber);
      pNextNode = 0;
    }

    void copy(const State& aState) {
      for (uint16_t i=0;i<aState.pNumber;++i) {
        pColors[i] = aState[i];
      }
      pMaxColor = aState.getMaxColor();
      pLastColor = aState.getLastColor();
      pNextNode = aState.getNode();
    }

    void clear() {
      for (uint16_t i=0;i<pNumber;++i) {
        pColors[i] = 0;
      }
    }
};

#endif
// vim: ts=2 fdm=marker syntax=cpp expandtab sw=2
